/*
 * utils/memory.hh - Macros and functions for memory manipulation.
 * Copyright (C) 2007  Mikhail Vorozhtsov
 * See the LICENSE section of the README file for details.
 */

/* $Id$ */

#ifndef HEADER_UTILS_MEMORY_HH
#define HEADER_UTILS_MEMORY_HH

START_NAMESPACE (utils)

#define KB(x) ((u64_t) (x) << 10)
#define MB(x) ((u64_t) (x) << 20)
#define GB(x) ((u64_t) (x) << 30)
#define TB(x) ((u64_t) (x) << 40)

#define KBS(x) ((u64_t) (x) >> 10)
#define MBS(x) ((u64_t) (x) >> 20)
#define GBS(x) ((u64_t) (x) >> 30)
#define TBS(x) ((u64_t) (x) >> 40)

#define ALIGN(x,b) (((x) + (b) - 1) & ~((b) - 1))
#define CUT(x,b) ((x) & ~((b) - 1))

INLINE
static bool
in_range_p (word_t addr, word_t start, word_t end, word_t boundary = 1)
{
  return addr >= CUT (start, boundary) && addr < ALIGN (end, boundary);
}

INLINE
static void *
zero (void *ptr, word_t size)
{
  void *result = ptr;

  for (; size > 0; --size)
    *((char *) ptr++) = 0;

  return result;
}

INLINE
static word_t
length (const char *str)
{
  word_t result = 0;

  while (*(str++))
    ++result;

  return result;
}

INLINE
static char *
cpz (const char *src, char *dst)
{
  char *result = dst;

  for (char b = *(src++); b; b = *(src++), ++dst)
    *dst = b;

  return result;
}

INLINE
static char *
cpz (const char *src, char *dst, word_t n)
{
  char *result = dst;

  for (char b = *(src++); b && n > 0; b = *(src++), ++dst, --n)
    *dst = b;

  *dst = 0;

  return result;
}

INLINE
static void *
cp (const void *src, void *dst, word_t n)
{
  void *result = dst;

  for (u8_t b = *(const u8_t *) (src++); n > 0;
       b = *(const u8_t *) (src++), ++dst, --n)
    *((u8_t *) dst) = b;

  return result;
}

INLINE
static int
cmpz (const char *str1, const char *str2)
{
  while (1)
    {
      u8_t c1 = *(str1++), c2 = *(str2++);

      if (c1 < c2)
        return -1;
      if (c1 > c2)
        return 1;

      if (c1 == 0)
        return 0;
    }
}

INLINE
static int
cmpz (const char *str1, word_t n1, const char *str2)
{
  for (; n1 > 0; --n1)
    {
      u8_t c1 = *(str1++), c2 = *(str2++);

      if (c1 < c2)
        return -1;
      if (c1 > c2)
        return 1;

      if (c1 == 0)
        return 0;
    }

  return *str2 == 0 ? 0 : 1;
}

INLINE
static int
cmpz (const char *str1, const char *str2, word_t n)
{
  for (; n > 0; --n)
    {
      u8_t c1 = *(str1++), c2 = *(str2++);

      if (c1 < c2)
        return -1;
      if (c1 > c2)
        return 1;

      if (c1 == 0)
        return 0;
    }

  return 0;
}

INLINE
static int
cmp (const void *ptr1, const void *ptr2, word_t n)
{
  for (; n > 0; --n)
    {
      u8_t c1 = *((const char *) ptr1++), c2 = *((const char *) ptr2++);

      if (c1 < c2)
        return -1;
      if (c1 > c2)
        return 1;
    }

  return 0;
}

END_NAMESPACE

#endif /* HEADER_UTILS_MEMORY_HH */

